
package edu.chalmers.AV_2DPlatformerFramework.Model;

import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;

/**
 * I simple class consisting of several textures to play in a predetermined order.
 * May be created with uniform or distributed screen time. For most uses, uniform is recommended.
 * v1.0
 * @author Richard Sundqvist
 */
public class AnimatedTexture extends Texture{
    
    //Accessible
    private Texture currentTexture;
    private final boolean uniformMode;
    private int currentTextureIndex = 0;
    private int currentTextureTimesDrawn = 0;
    
    //Inaccessible
    private final int screenTime;
    private final int screenTimeDistribution[];
    private final Texture[] TEXTURES;   
    
    
    //-------------------------------------------------------------------------------------------
    //CONSTRUCTOR
    //-------------------------------------------------------------------------------------------
    
    /**
     * Creates a new AnimatedTexture with the supplied texture sequence with uniform screen time.
     * @param textureSequence The Texture sequence to use.
     * @param screenTime The number of cycles each Texture should get.
     */
    public AnimatedTexture(Texture[] textureSequence, int screenTime){ 
        super(textureSequence[0].getImage(), new Rectangle2D.Double());  
        
        uniformMode = true;
        TEXTURES = textureSequence;
        currentTexture = TEXTURES[0];
        
        this.screenTime = screenTime;
        screenTimeDistribution = null; //Not used in the mode.
    }
    /**
     * Creates a new AnimatedTexture with the supplied texture sequence with distributed screen time.
     * @param textureSequence The Texture sequence to use.
     * @param screenTimeDistribution The number of cycles each individual screen gets.
     */
    public AnimatedTexture(Texture[] textureSequence, int[] screenTimeDistribution){
        super(textureSequence[0].getImage(), textureSequence[0].getAnchorRect());   
        
        uniformMode = false;
        TEXTURES = textureSequence;
        currentTexture = TEXTURES[0];
        
        this.screenTimeDistribution = screenTimeDistribution;
        screenTime = 0; //Not used in this mode
    }
    
    
    //-------------------------------------------------------------------------------------------
    //CONSTRUCTOR END
    //-------------------------------------------------------------------------------------------
    
    /**
     * Draws the currently queued texture using the g2d provided, and moves the current index.
     * WARNING: Affects what getUpdatedTexture() will return!
     * @param g2d The graphics context to use.
     * @param anchor The anchor to use when drawing.
     * @param reset Will reset g2d settings before returning if true.
     * @deprecated Should use GetVisual in GameObject.
     */
    @Override
    @Deprecated
    public void drawMe(Graphics2D g2d, Rectangle2D anchor, boolean reset){
        if (uniformMode){
            currentTexture.drawMe(g2d, anchor, reset);
            if (screenTime >= currentTextureTimesDrawn)
            updateTextureIndex();
        } else {
            currentTexture.drawMe(g2d, anchor, reset);
            if (screenTimeDistribution[currentTextureIndex] >= currentTextureTimesDrawn)
                updateTextureIndex();
        }
    }
    
    /**
     * Returns the next Texture in queue for this AnimatedTexture, and updates the queue.
     * @return The next Texture which should be drawn.
     */
    public Texture getVisual(){
        Texture ans;
        currentTextureTimesDrawn++;
        ans = TEXTURES[currentTextureIndex];
        
        if (uniformMode){
            if (currentTextureTimesDrawn >= screenTime)
                updateTextureIndex();

        } else { //Distributed mode
            if (currentTextureTimesDrawn >= screenTimeDistribution[currentTextureIndex])
                updateTextureIndex();
        }
        return ans;
    }
    
    @Override
    public Texture getUpdatedTexture(Rectangle2D newAnchor){
        return getVisual().getUpdatedTexture(newAnchor);
    }
    
    /**
     * Updates the current texture index, resets the drawn counter and returns to
     * index 0 if the index attempts to step out of bounds. Ignores screen time.
     */
    private void updateTextureIndex(){
            currentTextureIndex++;
            currentTextureIndex = currentTextureIndex%TEXTURES.length;
            
            currentTexture = TEXTURES[currentTextureIndex];
            currentTextureTimesDrawn = 0;
    }
    
    /**
     * Returns the current texture, the one which will be used by drawMe(), 
     * unless you've set it to be drawn zero times and disabled Uniform Mode.
     * @return The current Texture.
     */
    public Texture getCurrentTexture(){
        return currentTexture;
    }
    
    /**
     * Returns true if this AnimatedTexture is currently giving all textures
     * in it array equal time.
     * @return True if the current AnimatedTexture is in Uniform Mode.
     */
    public boolean isInUniformMode(){
        return uniformMode;
    }
    /**
     * Get the index of the current Texture;
     * @return The index of the current Texture.
     */
    public int getCurrentTextureIndex(){
        return currentTextureIndex;
    }
    /**
     * Gets the number of times the current Texture has been drawn.
     * @return The number of times the current Texture has been drawn.
     */
    public int getCurrentTextureTimesDrawn(){
        return currentTextureTimesDrawn;
    }
    /**
     * Reset the currentTextureTimesDrawn counter to 0.
     */
    public void resetCurrentTextureTimesDrawn(){
        currentTextureTimesDrawn = 0;
    }
    /**
     * Increment the currentTextureTimesDrawn by 1.
     */
    public void incrementCurrentTextureTimesDrawn(){
        currentTextureTimesDrawn++;
    }
    /**
     * Increment the CurrentTextureIndex, resets to 0 if the index moves out of bounds.
     */
    public void incrementCurrentTextureIndex(){
        updateTextureIndex();
    }   
    
    
    /**
     * Deep copy of this Animated Texture.
     * Includes currentTextureIndex and currentTextureTimesDrawn. Necessary for AT to work during with chase mode in View.
     * @return A deep copy of this AnimatedTexture.
     */
    @Override
    public AnimatedTexture copy(){
        AnimatedTexture copy;
        
        
        if (uniformMode){
            copy = new AnimatedTexture(TEXTURES.clone(), 
                    screenTime);
        } else {
            copy = new AnimatedTexture(TEXTURES.clone(), 
                    screenTimeDistribution.clone());
        }
       
        copy.currentTexture = this.currentTexture;
        copy.currentTextureIndex = this.currentTextureIndex;
        copy.currentTextureTimesDrawn = this.currentTextureTimesDrawn;

        return copy; 
    }
}
